classdef RequirementsDataTransformer
    % RequirementsDataTransformer - 需求数据转换器（静态工具类）
    %
    % 功能：
    % - 需求数据格式转换（SLREQX → GUI表格格式）
    % - 需求数据过滤（按状态、优先级、类型、搜索关键字）
    % - 需求数据验证和格式化
    %
    % 设计原则：
    % - 遵循DO-178规则第4条：业务逻辑与GUI分离
    % - 遵循DO-178规则第2条：明确错误处理，不使用fallback机制
    % - 纯静态方法，无状态，便于测试
    %
    % 使用示例：
    %   % 转换需求数据为表格格式
    %   tableData = RequirementsDataTransformer.convertToTableFormat(reqData);
    %
    %   % 过滤需求数据
    %   filters = struct('status', 'Approved', 'priority', 'High', 'searchText', 'safety');
    %   filteredData = RequirementsDataTransformer.filterRequirements(tableData, filters);
    %
    % 作者：DO-178项目开发团队
    % 日期：2025-10-04
    % 版本：1.0
    
    methods (Static)
        
        %% ==================== 数据转换 ====================
        
        function tableData = convertToTableFormat(reqData)
            % 将SLREQX需求数据转换为GUI表格格式
            % 输入：reqData - 需求数据（cell array或struct array）
            % 输出：tableData - 表格数据（cell array）
            %       格式：{需求ID, 摘要, 状态, 优先级, 类型, 验证方法, 创建日期}
            
            tableData = {};
            
            if isempty(reqData)
                return;
            end
            
            % 处理cell array格式（loadslreqx返回格式）
            if iscell(reqData)
                % 假设第一行是列名，从第二行开始是数据
                if size(reqData, 1) > 1
                    tableData = reqData(2:end, :);
                end
            % 处理struct array格式
            elseif isstruct(reqData)
                for i = 1:length(reqData)
                    req = reqData(i);
                    tableData = [tableData; RequirementsDataTransformer.processRequirementRecord(req)]; %#ok<AGROW>
                end
            end
        end
        
        function recordRow = processRequirementRecord(req)
            % 处理单条需求记录
            % 输入：req - 需求结构体
            % 输出：recordRow - 单行表格数据（1x7 cell array）
            
            recordRow = {};
            
            if ~isstruct(req)
                return;
            end
            
            % 提取字段（使用安全的字段访问）
            reqID = RequirementsDataTransformer.getFieldValue(req, 'id', '');
            summary = RequirementsDataTransformer.getFieldValue(req, 'summary', '');
            status = RequirementsDataTransformer.getFieldValue(req, 'status', 'Draft');
            priority = RequirementsDataTransformer.getFieldValue(req, 'priority', 'Medium');
            type = RequirementsDataTransformer.getFieldValue(req, 'type', 'Functional');
            verificationMethod = RequirementsDataTransformer.getFieldValue(req, 'verificationMethod', 'Test');
            
            % 日期格式化
            if isfield(req, 'createdDate')
                if isdatetime(req.createdDate)
                    createdDate = datestr(req.createdDate, 'yyyy-mm-dd');
                elseif ischar(req.createdDate) || isstring(req.createdDate)
                    createdDate = char(req.createdDate);
                else
                    createdDate = '';
                end
            else
                createdDate = '';
            end
            
            % 构造表格行
            recordRow = {reqID, summary, status, priority, type, verificationMethod, createdDate};
        end
        
        %% ==================== 数据过滤 ====================
        
        function filteredData = filterRequirements(originalData, filters)
            % 过滤需求数据 - 动态过滤器支持
            % 输入：
            %   originalData - 原始表格数据（cell array）
            %   filters - 过滤条件结构体（字段名对应属性名）
            %       例如：filters.Status = '已验证'
            %            filters.Priority = '高'
            %            filters.searchText = 'safety'
            % 输出：filteredData - 过滤后的表格数据
            %
            % 说明：
            %   - 此方法现在支持动态过滤器，不再硬编码列索引
            %   - 过滤器字段名对应列标题（不区分大小写）
            %   - "全部"值表示不过滤该属性
            %   - searchText会在所有文本列中搜索
            
            filteredData = originalData;
            
            if isempty(originalData)
                return;
            end
            
            % 验证数据格式：确保至少有2列（ID和Summary）
            if size(originalData, 2) < 2
                fprintf('❌ 需求数据过滤错误: 数据列数不足（需要至少2列，实际%d列）\n', size(originalData, 2));
                return;
            end
            
            % 如果没有过滤条件，直接返回
            if isempty(filters) || ~isstruct(filters)
                return;
            end
            
            % 获取过滤器字段名
            filterFields = fieldnames(filters);
            
            % 应用每个过滤器
            for i = 1:length(filterFields)
                fieldName = filterFields{i};
                filterValue = filters.(fieldName);
                
                % 跳过空值
                if isempty(filterValue)
                    continue;
                end
                
                % 特殊处理：searchText - 全文搜索
                if strcmp(fieldName, 'searchText')
                    filteredData = RequirementsDataTransformer.applySearchFilter(filteredData, filterValue);
                    continue;
                end
                
                % 普通属性过滤
                % 跳过"全部"值
                if ischar(filterValue) && strcmp(filterValue, '全部')
                    continue;
                end
                
                % 根据属性名过滤（不区分大小写匹配）
                filteredData = RequirementsDataTransformer.applyPropertyFilter(filteredData, fieldName, filterValue);
            end
            
            % 输出过滤结果统计
            fprintf('✅ 需求过滤完成: 从 %d 条需求筛选出 %d 条\n', ...
                size(originalData, 1), size(filteredData, 1));
        end
        
        function filteredData = applyPropertyFilter(data, propertyName, filterValue)
            % 应用单个属性过滤器
            % 输入：
            %   data - 数据cell array
            %   propertyName - 属性名称
            %   filterValue - 过滤值
            % 输出：filteredData - 过滤后的数据
            
            filteredData = data;
            
            if isempty(data)
                return;
            end
            
            % 查找匹配的列（通过列名，不区分大小写）
            % 注意：这里假设第一行是列名，但实际上originalData已经是纯数据
            % 我们需要通过属性名匹配，这需要额外的上下文信息
            % 简化方案：使用标准列顺序约定
            
            % 标准列映射（基于常见配置）
            columnMap = struct(...
                'Id', 1, ...
                'Summary', 2, ...
                'Status', 3, ...
                'Priority', 4, ...
                'Type', 5, ...
                'Verify', 6, ...
                'CreatedOn', 7 ...
            );
            
            % 查找列索引
            columnIndex = [];
            if isfield(columnMap, propertyName)
                columnIndex = columnMap.(propertyName);
            else
                % 尝试不区分大小写匹配
                fields = fieldnames(columnMap);
                for i = 1:length(fields)
                    if strcmpi(fields{i}, propertyName)
                        columnIndex = columnMap.(fields{i});
                        break;
                    end
                end
            end
            
            % 如果找不到列，返回原数据
            if isempty(columnIndex) || columnIndex > size(data, 2)
                fprintf('⚠️ 未找到属性"%s"对应的列，跳过此过滤器\n', propertyName);
                return;
            end
            
            % 应用过滤
            filterMask = false(size(data, 1), 1);
            for i = 1:size(data, 1)
                cellValue = data{i, columnIndex};
                if ischar(cellValue) || isstring(cellValue)
                    filterMask(i) = strcmp(char(cellValue), char(filterValue));
                end
            end
            
            filteredData = data(filterMask, :);
        end
        
        function filteredData = applySearchFilter(data, searchText)
            % 应用全文搜索过滤器
            % 输入：
            %   data - 数据cell array
            %   searchText - 搜索文本
            % 输出：filteredData - 过滤后的数据
            
            filteredData = data;
            
            if isempty(data) || isempty(searchText)
                return;
            end
            
            searchMask = false(size(data, 1), 1);
            
            for i = 1:size(data, 1)
                % 在所有文本列中搜索
                rowMatch = false;
                for j = 1:min(size(data, 2), 3)  % 只在前3列搜索（ID、Summary、Description）
                    cellValue = data{i, j};
                    if (ischar(cellValue) || isstring(cellValue)) && ...
                       contains(lower(char(cellValue)), lower(searchText))
                        rowMatch = true;
                        break;
                    end
                end
                searchMask(i) = rowMatch;
            end
            
            filteredData = data(searchMask, :);
        end
        
        %% ==================== 数据验证 ====================
        
        function isValid = validateRequirementData(reqData)
            % 验证需求数据格式
            % 输入：reqData - 需求数据（cell array或struct）
            % 输出：isValid - 是否有效（true/false）
            
            isValid = false;
            
            if isempty(reqData)
                fprintf('⚠️ 需求数据为空\n');
                return;
            end
            
            if iscell(reqData)
                % 验证cell array格式
                if size(reqData, 2) < 7
                    fprintf('❌ 需求数据必须有至少7列（实际%d列）\n', size(reqData, 2));
                    return;
                end
            elseif isstruct(reqData)
                % 验证struct格式
                requiredFields = {'id', 'summary'};
                for i = 1:length(requiredFields)
                    field = requiredFields{i};
                    if ~isfield(reqData, field)
                        fprintf('❌ 需求数据缺少必填字段: %s\n', field);
                        return;
                    end
                end
            else
                fprintf('❌ 需求数据必须是cell array或struct格式\n');
                return;
            end
            
            isValid = true;
        end
        
        function isValid = validateTableData(tableData)
            % 验证表格数据格式
            % 输入：tableData - 表格数据（cell array）
            % 输出：isValid - 是否有效（true/false）
            
            isValid = false;
            
            if isempty(tableData)
                fprintf('⚠️ 表格数据为空\n');
                return;
            end
            
            if ~iscell(tableData)
                fprintf('❌ 表格数据必须是cell array\n');
                return;
            end
            
            if size(tableData, 2) ~= 7
                fprintf('❌ 表格数据必须有7列（实际%d列）\n', size(tableData, 2));
                return;
            end
            
            isValid = true;
        end
        
        %% ==================== 数据格式化 ====================
        
        function formattedData = formatDateColumn(tableData, columnIndex)
            % 格式化日期列
            % 输入：
            %   tableData - 表格数据
            %   columnIndex - 日期列索引（默认为7）
            % 输出：formattedData - 格式化后的数据
            
            if nargin < 2
                columnIndex = 7;
            end
            
            formattedData = tableData;
            
            if isempty(tableData) || size(tableData, 2) < columnIndex
                return;
            end
            
            for i = 1:size(tableData, 1)
                dateStr = tableData{i, columnIndex};
                if ~isempty(dateStr)
                    % 尝试格式化日期
                    try
                        dt = datetime(dateStr);
                        formattedData{i, columnIndex} = datestr(dt, 'yyyy-mm-dd');
                    catch
                        % 保持原值
                    end
                end
            end
        end
        
        function statusText = formatStatus(status)
            % 格式化状态文本（中文映射）
            % 输入：status - 状态字符串（英文）
            % 输出：statusText - 格式化后的状态（中文）
            
            statusMap = containers.Map(...
                {'Draft', 'In Review', 'Approved', 'Rejected', 'Obsolete'}, ...
                {'草稿', '审查中', '已批准', '已拒绝', '已废弃'});
            
            if statusMap.isKey(status)
                statusText = statusMap(status);
            else
                statusText = status;
            end
        end
        
        function priorityText = formatPriority(priority)
            % 格式化优先级文本（中文映射）
            % 输入：priority - 优先级字符串（英文）
            % 输出：priorityText - 格式化后的优先级（中文）
            
            priorityMap = containers.Map(...
                {'Critical', 'High', 'Medium', 'Low'}, ...
                {'关键', '高', '中', '低'});
            
            if priorityMap.isKey(priority)
                priorityText = priorityMap(priority);
            else
                priorityText = priority;
            end
        end
        
        function typeText = formatType(type)
            % 格式化需求类型文本（中文映射）
            % 输入：type - 类型字符串（英文）
            % 输出：typeText - 格式化后的类型（中文）
            
            typeMap = containers.Map(...
                {'Functional', 'Performance', 'Interface', 'Safety', 'Other'}, ...
                {'功能', '性能', '接口', '安全', '其他'});
            
            if typeMap.isKey(type)
                typeText = typeMap(type);
            else
                typeText = type;
            end
        end
        
        %% ==================== 工具方法 ====================
        
        function value = getFieldValue(structData, fieldName, defaultValue)
            % 安全地获取结构体字段值
            % 输入：
            %   structData - 结构体
            %   fieldName - 字段名
            %   defaultValue - 默认值
            % 输出：value - 字段值或默认值
            
            if isfield(structData, fieldName) && ~isempty(structData.(fieldName))
                value = structData.(fieldName);
            else
                value = defaultValue;
            end
        end
        
        function summary = generateRequirementsSummary(tableData)
            % 生成需求数据统计摘要
            % 输入：tableData - 表格数据
            % 输出：summary - 统计摘要结构体
            
            summary = struct();
            summary.totalCount = size(tableData, 1);
            
            if summary.totalCount == 0
                return;
            end
            
            % 统计状态分布（第3列）
            statusColumn = tableData(:, 3);
            uniqueStatuses = unique(statusColumn);
            summary.statusDistribution = struct();
            for i = 1:length(uniqueStatuses)
                status = uniqueStatuses{i};
                count = sum(strcmp(statusColumn, status));
                summary.statusDistribution.(matlab.lang.makeValidName(status)) = count;
            end
            
            % 统计优先级分布（第4列）
            priorityColumn = tableData(:, 4);
            uniquePriorities = unique(priorityColumn);
            summary.priorityDistribution = struct();
            for i = 1:length(uniquePriorities)
                priority = uniquePriorities{i};
                count = sum(strcmp(priorityColumn, priority));
                summary.priorityDistribution.(matlab.lang.makeValidName(priority)) = count;
            end
            
            % 统计类型分布（第5列）
            typeColumn = tableData(:, 5);
            uniqueTypes = unique(typeColumn);
            summary.typeDistribution = struct();
            for i = 1:length(uniqueTypes)
                type = uniqueTypes{i};
                count = sum(strcmp(typeColumn, type));
                summary.typeDistribution.(matlab.lang.makeValidName(type)) = count;
            end
            
            fprintf('📊 需求数据统计: 共 %d 条需求\n', summary.totalCount);
            fprintf('   状态分布: %s\n', jsonencode(summary.statusDistribution));
            fprintf('   优先级分布: %s\n', jsonencode(summary.priorityDistribution));
            fprintf('   类型分布: %s\n', jsonencode(summary.typeDistribution));
        end
        
        function reqTree = convertTreeDataToUITree(treeData, parentNode, uitreefunc)
            % 将需求树数据转换为UI树节点
            % 输入：
            %   treeData - 树数据结构
            %   parentNode - 父节点（uitreenode）
            %   uitreefunc - 创建树节点的函数句柄
            % 输出：reqTree - UI树根节点
            
            if isempty(treeData)
                reqTree = [];
                return;
            end
            
            % 创建根节点或子节点
            if nargin < 2 || isempty(parentNode)
                % 创建根节点
                reqTree = uitreefunc('Text', treeData.name, 'NodeData', treeData);
                currentNode = reqTree;
            else
                % 创建子节点
                currentNode = uitreenode(parentNode, 'Text', treeData.name, 'NodeData', treeData);
                reqTree = currentNode;
            end
            
            % 递归添加子节点
            if isfield(treeData, 'children') && ~isempty(treeData.children)
                for i = 1:length(treeData.children)
                    childData = treeData.children{i};
                    RequirementsDataTransformer.convertTreeDataToUITree(...
                        childData, currentNode, @uitreenode);
                end
            end
        end
        
    end
end




